home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-21 | 17.2 KB | 530 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWObjecH.cpp
- // Release Version: $ 1.0d1 $
- //
- // Creation Date: 3/28/94
- //
- // Copyright: © 1993, 1994 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FWPLATME_H
- #include <FWPlatMe.h>
- #endif
-
- #ifndef FWOBJECH_H
- #include <FWObjecH.h>
- #endif
-
-
- //========================================================================================
- // CLASS FW_CPrivChunkyBlock
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlock::FW_CPrivChunkyBlock
- //----------------------------------------------------------------------------------------
-
- FW_CPrivChunkyBlock::FW_CPrivChunkyBlock()
- {
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlock::FW_CPrivChunkyBlock
- //----------------------------------------------------------------------------------------
-
- FW_CPrivChunkyBlock::FW_CPrivChunkyBlock(unsigned int sizeIndex,
- unsigned int blockIndex)
- {
- SetSizeIndex(sizeIndex);
- SetBlockIndex(blockIndex);
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlock::GetChunk
- //----------------------------------------------------------------------------------------
-
- FW_CChunk* FW_CPrivChunkyBlock::GetChunk(FW_BlockSize blkSize)
- {
- FW_CChunk *chk
- = (FW_CChunk *) ((FW_BytePtr) this - sizeof(FW_SPrivChunkHeader) - blkSize * GetBlockIndex());
- return chk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlock::IsBusy
- //----------------------------------------------------------------------------------------
-
- Boolean FW_CPrivChunkyBlock::IsBusy(FW_BlockSize blockSize)
- {
- return this->GetChunk(blockSize)->IsBlockBusy(GetBlockIndex());
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlock::SetBusy
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivChunkyBlock::SetBusy(FW_BlockSize blockSize, Boolean busy)
- {
- this->GetChunk(blockSize)->SetBlockBusy(GetBlockIndex(), busy);
- }
-
-
- //========================================================================================
- // FW_CChunk
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CChunk::FW_CChunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CChunk::FW_CChunk(short blocksPerChunk,
- unsigned int sizeIndex,
- FW_BlockSize blockSize)
- {
- fHeader.fBlockBusyBits = 0;
- void* blkPtr = (void *) ((FW_BytePtr) this + sizeof(FW_SPrivChunkHeader));
- for (unsigned int i = 0; i < blocksPerChunk; i++)
- {
- FW_CPrivChunkyBlock *blk = new(blkPtr)FW_CPrivChunkyBlock(sizeIndex, i);
- blkPtr = (void *) ((FW_BytePtr) blkPtr + blockSize);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CChunk::IsBlockBusy
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CChunk::IsBlockBusy(unsigned int whichBlock)
- {
- unsigned short mask = 0x0001;
-
- for (short i = 0; i < whichBlock; i++)
- mask = mask << 1;
-
- return (fHeader.fBlockBusyBits & mask) != 0;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CChunk::SetBlockBusy
- //----------------------------------------------------------------------------------------
-
- void FW_CChunk::SetBlockBusy(unsigned int whichBlock, Boolean busy)
- {
- unsigned short mask = 0x0001;
-
- for (short i = 0; i < whichBlock; i++)
- mask = mask << 1;
-
- if (busy)
- fHeader.fBlockBusyBits |= mask;
- else
- fHeader.fBlockBusyBits &= ~mask;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CChunk::GetBlock
- //----------------------------------------------------------------------------------------
-
- FW_CPrivChunkyBlock* FW_CChunk::GetBlock(unsigned int blkIndex, FW_BlockSize blkSize)
- {
- FW_CPrivChunkyBlock * blk
- = (FW_CPrivChunkyBlock *) ((FW_BytePtr) this + sizeof(FW_SPrivChunkHeader) + blkIndex * blkSize);
- return blk;
- }
-
-
- //========================================================================================
- // FW_CObjectHeap
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::FW_CObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CObjectHeap::FW_CObjectHeap(unsigned long initialSize,
- unsigned long incrementSize,
- short blocksPerChunk) :
- FW_CBestFitHeap(initialSize, incrementSize),
- fBlockSizes(ObjectHeap_kDefaultBlockSizes)
- {
- #ifdef FW_DEBUG
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::FW_CObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CObjectHeap::FW_CObjectHeap(const FW_BlockSize* blockSizes,
- unsigned long initialSize,
- unsigned long incrementSize,
- short blocksPerChunk) :
- FW_CBestFitHeap(initialSize, incrementSize),
- fBlockSizes(blockSizes)
- {
- #ifdef FW_DEBUG
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::IObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::IObjectHeap()
- {
- this->IBestFitHeap();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::~FW_CObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CObjectHeap::~FW_CObjectHeap()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::DoAllocate
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void* FW_CObjectHeap::DoAllocate(FW_BlockSize size, FW_BlockSize& allocatedSize)
- {
- if (size + FW_CPrivChunkyBlock::kBusyOverhead > fBlockSizes[fNumberOfBlockSizes - 1])
- return FW_CBestFitHeap::DoAllocate(size, allocatedSize);
- else
- {
- unsigned int sizeIndex = this->SizeIndex(size);
- allocatedSize = fBlockSizes[sizeIndex] - FW_CPrivChunkyBlock::kBusyOverhead;
- return this->AllocateBlock(sizeIndex);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::DoBlockSize
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_BlockSize FW_CObjectHeap::DoBlockSize(const void* ptr) const
- {
- FW_CPrivChunkyBlock *block
- = (FW_CPrivChunkyBlock *) ((FW_BytePtr) ptr - FW_CPrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == FW_CPrivBestFitBlock::kBlockTypeId)
- return FW_CBestFitHeap::DoBlockSize(ptr);
- else
- return fBlockSizes[block->GetSizeIndex()] - FW_CPrivChunkyBlock::kBusyOverhead;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::DoFree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::DoFree(void* ptr)
- {
- FW_CPrivChunkyBlock *block
- = (FW_CPrivChunkyBlock *) ((FW_BytePtr) ptr - FW_CPrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == FW_CPrivBestFitBlock::kBlockTypeId)
- FW_CBestFitHeap::DoFree(ptr);
- else
- this->FreeBlock(block);
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::DoIsValidBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CObjectHeap::DoIsValidBlock(void* ptr) const
- {
- Boolean isBlockValid = false;
-
- FW_CPrivChunkyBlock *block
- = (FW_CPrivChunkyBlock *) ((FW_BytePtr) ptr - FW_CPrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == FW_CPrivBestFitBlock::kBlockTypeId)
- isBlockValid = FW_CBestFitHeap::DoIsValidBlock(ptr);
- else
- isBlockValid
- = block->GetSizeIndex() <= fNumberOfBlockSizes &&
- block->GetBlockIndex() <= fBlocksPerChunk &&
- block->GetMagicNumber() == (unsigned int) FW_CPrivChunkyBlock::kMagicNumber;
-
- return isBlockValid;
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::DoReset
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::DoReset()
- {
- FW_CPrivChunkyBlockStack clr;
-
- for (int i = 0; i < fNumberOfBlockSizes; i++)
- fFreeLists[i] = clr;
-
- FW_CBestFitHeap::DoReset();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::AllocateBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void *FW_CObjectHeap::AllocateBlock(unsigned int sizeIndex)
- {
- if (fFreeLists[sizeIndex].Top() == NULL)
- this->CreateNewChunk(sizeIndex);
-
- FW_CPrivChunkyBlock * blk = fFreeLists[sizeIndex].Pop();
- if (blk != NULL)
- {
- blk->SetBusy(fBlockSizes[sizeIndex], true);
- return (void *) ((FW_BytePtr) blk + FW_CPrivChunkyBlock::kBusyOverhead);
- }
- else
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::CreateNewChunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::CreateNewChunk(unsigned int sizeIndex)
- {
- FW_BlockSize allocatedSize;
- FW_BlockSize allocSize = sizeof(FW_SPrivChunkHeader) + fBlocksPerChunk * fBlockSizes[sizeIndex];
- FW_CChunk * chk = new(FW_CBestFitHeap::DoAllocate(allocSize, allocatedSize))FW_CChunk(fBlocksPerChunk, sizeIndex, fBlockSizes[sizeIndex]);
- if (chk != NULL)
- {
- for (unsigned int i = 0; i < fBlocksPerChunk; i++)
- {
- FW_CPrivChunkyBlock * blk = chk->GetBlock(i, fBlockSizes[sizeIndex]);
- blk->SetBusy(fBlockSizes[sizeIndex], false);
- fFreeLists[sizeIndex].Push(blk);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::FreeBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::FreeBlock(FW_CPrivChunkyBlock* blk)
- {
- blk->SetBusy(fBlockSizes[blk->GetSizeIndex()], false);
- fFreeLists[blk->GetSizeIndex()].Push(blk);
-
- // Check to see if all blocks in this block's FW_CChunk are free, if so then free the
- // FW_CChunk.
-
- FW_CChunk *chk = blk->GetChunk(fBlockSizes[blk->GetSizeIndex()]);
- if (!chk->IsBusy())
- {
- // Remove blocks in this FW_CChunk from the free list. This is the achililles hill
- // of the Heap. Its difficult to remove blocks from a singly linked list
- // rapidly.
-
- void *begAddr = chk;
- void *endAddr = (void *) ((FW_BytePtr) chk +
- sizeof(FW_SPrivChunkHeader) +
- fBlocksPerChunk * fBlockSizes[chk->GetSizeIndex()]);
- fFreeLists[chk->GetSizeIndex()].RemoveRange(begAddr, endAddr);
- FW_CBestFitHeap::DoFree(chk);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::SizeIndex
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- unsigned int FW_CObjectHeap::SizeIndex(FW_BlockSize size)
- {
- for (unsigned int i = 0; i < fNumberOfBlockSizes; i++)
- if (size + FW_CPrivChunkyBlock::kBusyOverhead <= fBlockSizes[i])
- return i;
-
- // Uh oh! An internal error:
-
- PLATFORM_DEBUGGER_STRING("Internal error in FW_CObjectHeap::SizeIndex");
-
- return 0xFFFFFFFF; // the former way of handling the internal error
- // we leave it in to defeat an xlC warning
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CObjectHeap::CompilerCheck
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CObjectHeap::CompilerCheck()
- {
- FW_CBestFitHeap::CompilerCheck();
-
- FW_CPrivChunkyBlock block;
-
- block.SetSizeIndex(0xF);
- block.SetBlockIndex(0xE);
- block.SetBlockType(FW_CPrivChunkyBlock::kBlockTypeId);
- block.SetMagicNumber(0xC);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0xF);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0xE);
- PLATFORM_ASSERT(block.GetBlockType() == FW_CPrivChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != FW_CPrivBestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0xC);
-
- block.SetSizeIndex(0x7);
- block.SetBlockIndex(0x6);
- block.SetBlockType(FW_CPrivBestFitBlock::kBlockTypeId);
- block.SetMagicNumber(0x4);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0x7);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0x6);
- PLATFORM_ASSERT(block.GetBlockType() == FW_CPrivBestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != FW_CPrivChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0x4);
- }
- #endif
-
- //========================================================================================
- // FW_CPrivChunkyBlockStack
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::FW_CPrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlockStack::FW_CPrivChunkyBlockStack()
- {
- fHead.SetNext(NULL);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::FW_CPrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlockStack::FW_CPrivChunkyBlockStack(const FW_CPrivChunkyBlockStack& blk) :
- fHead(blk.fHead)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::operator=
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlockStack& FW_CPrivChunkyBlockStack::operator=(const FW_CPrivChunkyBlockStack& blk)
- {
- fHead = blk.fHead;
- return *this;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::Pop
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlock* FW_CPrivChunkyBlockStack::Pop()
- {
- FW_CPrivChunkyBlock * blk = fHead.GetNext();
- fHead.SetNext(blk->GetNext());
- return blk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::Push
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivChunkyBlockStack::Push(FW_CPrivChunkyBlock* blk)
- {
- blk->SetNext(fHead.GetNext());
- fHead.SetNext(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::RemoveRange
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivChunkyBlockStack::RemoveRange(void *begAddr, void *endAddr)
- {
- FW_CPrivChunkyBlock *prevBlk = &fHead;
- FW_CPrivChunkyBlock *curBlk = fHead.GetNext();
-
- while (curBlk != NULL)
- {
- void *curAddr = curBlk;
-
- if (curAddr >= begAddr && curAddr <= endAddr)
- {
- prevBlk->SetNext(curBlk->GetNext());
- curBlk = curBlk->GetNext();
- }
- else
- {
- prevBlk = curBlk;
- curBlk = curBlk->GetNext();
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::Top
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlock* FW_CPrivChunkyBlockStack::Top()
- {
- return fHead.GetNext();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivChunkyBlockStack::~FW_CPrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivChunkyBlockStack::~FW_CPrivChunkyBlockStack()
- {
- }
-
-